import { interface_data, interface_option } from './chartInterface'
let yList = []
class DrawMcLineChart {
  private ctx = null;
  private cWidth: number = 0; // 画布宽度
  private cHeight: number = 0; // 画布高度
  private ySplitNum: number = 6; // Y轴刻度，默认五
  private cSpaceT: number = 0; // 内部间距--上
  private cSpaceB: number = 0; // 内部间距--下
  private cSpaceL: number = 0; // 内部间距--左
  private cSpaceR: number = 0; // 内部间距--右
  private data: interface_data[] = []; // 数据
  private maxValue: number = 0; // 数据中的最大值
  private minValue: number = 0; // 数据中的最小值
  private dataLength: number = 0; // 数据总长度
  private maxW: number = 0; // y轴文本标签最长宽度
  private maxH: number = 0; // x轴文本标签最长高度
  private maxValW: number = 0; // 最长的数值
  private maxValH: number = 0; // 最高的文本
  private xSplitSpacing: number = 0; // x轴之间的分割间隔
  private ySplitSpacing: number = 0; // y轴之间的分割间隔
  private option: interface_option = {} // 配置信息
  private yAxis = {
    axisLine: { // 坐标轴轴线相关设置。
      show: true,
      lineStyle: {
        color: '#333',
        width: 1,
        type: 'solid'
      }
    },
    axisTick: { // 坐标轴刻度相关设置。
      show: true,
      interval: 4, // 与文本的间隔
      length: 5, // 刻度的长度
      lineStyle: {
        color: '#333',
        width: 1
      }
    },
    splitLine: { // 坐标轴中的分隔线。
      show: true,
      lineStyle: {
        color: '#ccc',
        width: 1
      }
    }
  }
  private xAxis = {
    axisLine: { // 坐标轴轴线相关设置。
      show: true,
      lineStyle: {
        color: '#333',
        width: 1,
        type: 'solid'
      }
    },
    axisTick: { // 坐标轴刻度相关设置。
      show: true,
      interval: 4,
      length: 5,
      lineStyle: {
        color: '#333',
        width: 1
      }
    },
    splitLine: { // 坐标轴中的分隔线。
      show: true,
      lineStyle: {
        color: '#ccc',
        width: 1
      }
    }
  }

  constructor(context, options) {
    this.ctx = context;
    this.cWidth = context.width;
    this.cHeight = context.height;
    const {data, cSpace, ...option} = options;
    this.option = option;
    this.data = data;
    this.dataLength = data.length;
    const values = data.map(item => item.value)
    this.maxValue = Math.max(...values);
    this.minValue = Math.min(...values, 0);
    // 赋值上下左右内间距, 如果是数组，只能穿数组长度为1、2、4，为1的时候就是四个方向都是一样的。为2的时候就是[上下、 左右]。为4的时候就是[上、右、下、左]
    if (Array.isArray(cSpace)) {
      switch (cSpace.length) {
        case 2:
          const [cSpaceTB, cSpaceLR] = cSpace
          this.cSpaceT = this.cSpaceB = cSpaceTB
          this.cSpaceL = this.cSpaceR = cSpaceLR
          break
        case 4:
          const [cSpaceT, cSpaceR, cSpaceB, cSpaceL] = cSpace
          this.cSpaceT = cSpaceT
          this.cSpaceB = cSpaceB
          this.cSpaceL = cSpaceL
          this.cSpaceR = cSpaceR
          break
        default:
        case 1:
          this.cSpaceT = this.cSpaceB = this.cSpaceL = this.cSpaceR = cSpace[0]
          break
      }
    } else {
      this.cSpaceT = this.cSpaceB = this.cSpaceL = this.cSpaceR = cSpace
    }
    // 获取最长宽度与最长高度
    const { axisTick: yAxisTick } = this.yAxis;
    const { axisTick: xAxisTick } = this.xAxis;
    this.data.forEach((item, index) => {
      const nameW = this.ctx.measureText(String(item.value)).width; // 获取文字的长度
      const valH = this.ctx.measureText(item.name).height; // 获取数据的高度
      this.maxValW = Math.max(nameW, this.maxValW)
      this.maxValH = Math.max(valH, this.maxValH)
      let leftW = nameW + this.cSpaceL
      // 绘画刻度线
      if (yAxisTick.show) {
        leftW = leftW + yAxisTick.interval + yAxisTick.length;
      }
      this.maxW = Math.max(leftW, this.maxW) // 计算出左边最大宽度
      let bottomH = valH + this.cSpaceB
      // 绘画刻度线
      if (xAxisTick.show) {
        bottomH = bottomH + xAxisTick.interval + xAxisTick.length;
      }
      this.maxH = Math.max(bottomH, this.maxH) // 计算出底边最大高度
    })
    this.ySplitSpacing = parseInt(String((this.cHeight - (this.cSpaceT + this.cSpaceB)) / this.ySplitNum))
    this.xSplitSpacing = parseInt(String((this.cWidth - (this.maxW + this.cSpaceR)) / this.dataLength))
    this.ctx.translate(0.5, 0.5);
  }
  // 设置画布样式
  private setCtxStyle (style) {
    for (const key in style) {
      this.ctx[key] = style[key];
    }
  }

  // 画线的方法
  private drawLine (x, y, X, Y) {
    this.ctx.beginPath();
    this.ctx.moveTo(x, y);
    this.ctx.lineTo(X, Y);
    this.ctx.stroke();
    this.ctx.closePath();
  }
  // 画标点
  private drawArc (x, y) {
    this.ctx.beginPath();
    this.ctx.arc(x, y, 3, 0, Math.PI * 2);
    this.ctx.fill();
    this.ctx.closePath();
  }

  private drawLineY() {
    const { fontSize, fontWeight, fontFamily, color } = this.option;
    // 设置文本属性
    this.ctx.font = `${color} ${fontWeight} ${fontSize}px ${fontFamily}`;
    // 绘制y轴分割线以及刻度线
    yList = []
    const { axisTick, splitLine, axisLine } = this.yAxis;
    const total = this.maxValue - this.minValue
    const splitNum = total / this.ySplitNum
    for (var i = 0; i <= this.ySplitNum; i++) {

      // console.log('2', splitNum, total, total - (splitNum * (i + 1)))
      const text = String(parseInt(String(total - (splitNum * (this.ySplitNum - (i - 1))))));
      const textWidth = this.ctx.measureText(text).width; // 获取文字的长度
      const textHeight = Math.ceil(this.ctx.measureText(text).height); // 获取文字的长度
      const commonY = this.ySplitSpacing * (this.ySplitNum - i) + this.cSpaceT
      yList.push(commonY)
      // 绘画文本标签
      // 右对齐
      const textX = this.cSpaceL + this.maxValW - textWidth;
      const textY = commonY + (textHeight / 2) - 2;
      this.ctx.fillText(text, textX, textY, 0);
      // 左对齐
      // this.ctx.fillText(text, this.cSpaceL, y + (textHeight / 2) - 2, 0);

      // 绘画刻度线
      if (axisTick.show) {
        const { color, width } = axisTick.lineStyle;
        const scaleX = this.maxW - axisTick.length;
        const scaleY = commonY;
        this.setCtxStyle({
          strokeStyle: color,
          lineWidth: width
        })
        this.drawLine(scaleX, scaleY, this.maxW, scaleY);
      }

      // 绘画分割线
      if (splitLine.show && i !== 0) {
        const { color, width } = splitLine.lineStyle;
        const splitY = commonY
        this.setCtxStyle({
          strokeStyle: color,
          lineWidth: width
        })
        this.drawLine(this.maxW, splitY, this.cWidth - this.cSpaceR, splitY);
      }
    }
    // 绘画Y轴线
    if (axisLine.show) {
      const { color, width } = axisLine.lineStyle;
      this.setCtxStyle({
        strokeStyle: color,
        lineWidth: width
      })
      this.ctx.beginPath();
      for (var i = 0; i < yList.length; i++) {
        if (i == 0) {
          this.ctx.moveTo(this.maxW, yList[i]);
        } else {
          this.ctx.lineTo(this.maxW, yList[i]);
        }
      }
      this.ctx.stroke();
      // this.drawLine(this.maxW, this.cSpaceT, this.maxW, this.cHeight - this.cSpaceB + this.maxH);
    }
  }

  private drawLineX() {
    const { fontSize, fontWeight, fontFamily, color } = this.option;
    // 设置文本属性
    this.ctx.font = `${color} ${fontWeight} ${fontSize}px ${fontFamily}`;
    const { axisTick, splitLine, axisLine } = this.xAxis;
    for (var i = 0; i <= this.dataLength; i++) {
      const commonX = this.xSplitSpacing * (i) + this.maxW
      const commonY = yList[0]
      let spacing = 0
      // 绘画刻度线
      if (axisTick.show) {
        const { color, width } = axisTick.lineStyle;
        const scaleX = commonX;
        const scaleY = commonY;
        this.setCtxStyle({
          strokeStyle: color,
          lineWidth: width
        })
        spacing = axisTick.interval + axisTick.length
        this.drawLine(scaleX, scaleY, scaleX, scaleY + axisTick.length);
      }

      if (i !== 0) {
        // 绘画文本
        const text = String(this.data[i - 1].name)
        const textWidth = this.ctx.measureText(text).width; // 获取文字的长度
        const textHeight = this.ctx.measureText(text).height; // 获取文字的长度
        this.ctx.fillText(text, commonX - textWidth / 2, commonY + textHeight + spacing, 0);

        // 绘画分割线
        if (splitLine.show) {
          const { color, width } = splitLine.lineStyle;
          const splitY = commonY
          this.setCtxStyle({
            strokeStyle: color,
            lineWidth: width
          })
          this.drawLine(commonX, commonY, commonX, yList[yList.length - 1]);
        }
      }
    }
    // 绘画X轴线
    if (axisLine.show) {
      const { color, width } = axisLine.lineStyle;
      this.setCtxStyle({
        strokeStyle: color,
        lineWidth: width
      })
      this.drawLine(this.maxW, yList[0], this.cWidth - this.cSpaceR, yList[0]);
    }
  }

  private drawFoldLines () {
    this.setCtxStyle({
      strokeStyle: "#ff18aeff",
      lineWidth: 2
    })
    const yScale = (this.cHeight - this.cSpaceT - this.cSpaceB) / this.maxValue
    //连线
    this.ctx.beginPath();
    const xList = []
    for (var i = 0; i < this.dataLength; i++) {
      const commonX = this.xSplitSpacing * (i + 1) + this.maxW
      var dotVal = Number(this.data[i].value);
      var y = (this.cHeight - this.cSpaceT) - parseInt(String(dotVal * yScale));
      xList.push(commonX)
      if (i == 0) {
        this.ctx.moveTo(commonX, y);
      } else {
        this.ctx.lineTo(commonX, y);
      }
    }
    this.ctx.stroke();
    // 背景
    this.ctx.lineTo(xList[xList.length - 1], this.cHeight - this.maxH);
    this.ctx.lineTo(xList[0], this.cHeight - this.maxH);
    // 背景渐变色
    // 柱状图渐变色
    var gradient = this.ctx.createLinearGradient(0, 0, 0, 300);
    gradient.addColorStop(0, 'rgba(133,171,212,0.6)');
    gradient.addColorStop(1, 'rgba(133,171,212,0.1)');
    this.ctx.fillStyle = gradient;
    this.ctx.fill();
    this.ctx.closePath();
    this.ctx.fillStyle = "#566a80";
    // 绘画标点与文本标签
    for (var i = 0; i < this.dataLength; i++) {
      const commonX = this.xSplitSpacing * (i + 1) + this.maxW
      var dotVal = Number(this.data[i].value);
      var y = (this.cHeight - this.cSpaceT) - parseInt(String(dotVal * yScale));
      this.drawArc(commonX, y); //绘制点
      // 绘画文本标签
      const text = String(dotVal)
      const textWidth = this.ctx.measureText(text).width; // 获取文字的长度
      const textHeight = this.ctx.measureText(text).height; // 获取文字的长度
      this.ctx.fillText(text, commonX - textWidth / 2, y - textHeight / 2); // 文字
    }
  }

  initChart() {
    this.drawLineY(); // 绘画Y轴
    this.drawLineX(); // 绘画X轴
    this.ctx.save();
    this.ctx.rotate(-Math.PI / 2);
    this.ctx.restore();
    this.drawFoldLines() // 绘画折线
  }
}

export {
  DrawMcLineChart
}